home *** CD-ROM | disk | FTP | other *** search
- /*
- * POP2 Client routines. Originally authored by Mike Stockett
- * (WA7DYX).
- * Modified 12 May 1991 by Mark Edwards (WA6SMN) to use new timer
- * facilities in NOS0423. Fixed type mismatches spotted by C++.
- * Modified 27 May 1990 by Allen Gwinn (N5CKP) for compatibility
- * with later releases (NOS0522).
- * Added into NOS by PA0GRI (and linted into "standard" C)
- *
- * Some code culled from previous releases of SMTP.
- *
- * Client routines for Simple Mail Transfer Protocol ala RFC821
- * A.D. Barksdale Garbee II, aka Bdale, N3EUA
- * Copyright 1986 Bdale Garbee, All Rights Reserved.
- * Permission granted for non-commercial copying and use, provided
- * this notice is retained.
- * Modified 14 June 1987 by P. Karn for symbolic target addresses,
- * also rebuilt locking mechanism
- * Copyright 1987 1988 David Trulli, All Rights Reserved.
- * Permission granted for non-commercial copying and use, provided
- * this notice is retained.
- */
- #include <stdio.h>
- #include <fcntl.h>
- #include <time.h>
- #include <setjmp.h>
- #ifdef UNIX
- #include <sys/types.h>
- #endif
- #ifdef __TURBOC__
- #include <dir.h>
- #include <io.h>
- #endif
- #include "global.h"
- #include "config.h"
-
- #ifdef POP2_CLIENT
- #ifdef ANSIPROTO
- #include <stdarg.h>
- #endif
- #include "mbuf.h"
- #include "cmdparse.h"
- #include "proc.h"
- #include "socket.h"
- #include "timer.h"
- #include "netuser.h"
- #include "dirutil.h"
- #include "files.h"
- #include "smtp.h"
-
- #define BUF_LEN 257
-
- /* mail separator */
- #define isNotSOM(x) ((strncmp(x,"From ",5) != 0))
-
- /* POP client control block */
- static struct pop_ccb {
- int socket; /* socket for this connection */
- char state; /* client state */
- #define CALL 0
- #define NMBR 3
- #define SIZE 5
- #define XFER 8
- #define EXIT 10
- char buf[BUF_LEN]; /* tcp input buffer pointer */
- char count; /* input buffer length */
- int folder_len; /* number of msgs in current folder */
- long msg_len; /* length of current msg */
- int msg_num; /* current message number */
- } *ccb;
- #define NULLCCB (struct pop_ccb *)0
-
- static int16 Popquiet = 0;
- static int32 mailhost = 0;
-
- static void pop_send __ARGS((int unused,void *cb1,void *p));
- static int poptick __ARGS((void));
- static FILE *fd;
-
- /* Command string specifications */
- static char near mailbox_name[20],
- username[20],
- password[20],
- Workfile_name[] ="mbox.pop",
- ackd_cmd[] = "ACKD\n",
- #ifdef POP_FOLDERS
- fold_cmd[] = "FOLD %s\n",
- #endif
- login_cmd[] = "HELO %s %s\n",
- /* nack_cmd[] = "NACK\n", /* Not implemented */
- quit_cmd[] = "QUIT\n",
- read_cur_cmd[] = "READ\n",
- retr_cmd[] = "RETR\n",
- greeting_rsp[] = "+ POP2 "; /* Response string keys */
- /* ok_rsp[] = "+ OK"; */
-
- static int
- domailbox(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- if(argc < 2 && mailbox_name[0] != '\0')
- tprintf("%s\n",mailbox_name);
- else {
- sprintf(mailbox_name,"%.18s",argv[1]);
- }
- return 0;
- }
-
- static int
- domailhost(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- int32 n;
-
- if(argc < 2) {
- tprintf("%s\n",inet_ntoa(mailhost));
- } else {
- if((n = resolve(argv[1])) == 0) {
- tprintf(Badhost,argv[1]);
- return 1;
- } else {
- mailhost = n;
- }
- }
- return 0;
- }
-
- static int
- popkick(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- return (poptick());
- }
-
- static int
- doquiet(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- return setintrc(&Popquiet,"POP2 quiet",argc,argv,0,3);
- }
-
- static struct timer popcli_t;
-
- static int
- dotimer(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- if(argc < 2) {
- tprintf("POP2 timer %lu/%lu s\n",
- read_timer(&popcli_t)/1000L,dur_timer(&popcli_t)/1000L);
- } else {
- stop_timer(&popcli_t);
- popcli_t.func = (void (*)())poptick; /* what to call on timeout */
- popcli_t.arg = NULLCHAR; /* dummy value */
- set_timer(&popcli_t,atol(argv[1])*1000L); /* set timer duration */
- start_timer(&popcli_t); /* and fire it up */
- }
- return 0;
- }
-
- static int
- douserdata(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- if (argc < 2 && username[0] != '\0')
- tprintf("%s\n",username);
- else if (argc != 3) {
- tputs("Usage: pop2 userdata <username> <password>\n");
- return 1;
- } else {
- sprintf(username,"%.18s",argv[1]);
- sprintf(password,"%.18s",argv[2]);
- }
- return 0;
- }
-
- int
- dopop2(int argc,char *argv[],void *p) {
- struct cmds Popcmds[] = {
- "mailbox", domailbox, 0, 0, NULLCHAR,
- "mailhost", domailhost, 0, 0, NULLCHAR,
- "kick", popkick, 0, 0, NULLCHAR,
- "quiet", doquiet, 0, 0, NULLCHAR,
- "timer", dotimer, 0, 0, NULLCHAR,
- "userdata", douserdata, 0, 0, NULLCHAR,
- NULLCHAR,
- };
- return subcmd(Popcmds,argc,argv,p);
- }
-
- static int
- poptick()
- {
- int error = 0;
-
- if (ccb == NULLCCB) {
- /* Don't start if any of the required parameters have not been specified */
- if (mailhost == 0) {
- tputs("POP2 Mailhost not set\n");
- error = 1;
- }
- if (mailbox_name[0] == '\0') {
- tputs("POP2 Mailbox not set\n");
- error = 1;
- }
- if (username[0] == '\0' || password[0] == '\0') {
- tputs("POP2 Username and/or password not set\n");
- error = 1;
- }
- if(error == 0) {
- if ((ccb = (struct pop_ccb *)mxallocw(sizeof(struct pop_ccb))) == NULLCCB) {
- tputs("Unable to allocate CCB\n");
- error = 1;
- } else {
- stop_timer(&popcli_t);
- newproc("POP2 Client",1024,pop_send,0,ccb,NULL,0);
- }
- }
- } else {
- start_timer(&popcli_t);
- }
- return error;
- }
-
- static void
- pop_send(unused,cb1,p)
- int unused;
- void *cb1;
- void *p;
- {
- struct sockaddr_in fsocket;
- FILE *mf;
- char mailbox_pathname[BUF_LEN];
-
- fsocket.sin_family = AF_INET;
- fsocket.sin_addr.s_addr = mailhost;
- fsocket.sin_port = IPPORT_POP2;
-
- ccb->socket = socket(AF_INET,SOCK_STREAM,0);
- sockmode(ccb->socket,SOCK_ASCII);
-
- if (connect(ccb->socket,(char *)&fsocket,SOCKSIZE) != -1) {
- log(ccb->socket,"POP2 connect");
- ccb->state = CALL;
- for(;;) {
- loop:
- if(ccb->state == EXIT) {
- usprintf(ccb->socket,quit_cmd);
- break;
- }
- if (recvline(ccb->socket,ccb->buf,BUF_LEN) == -1)
- break;
- rip(ccb->buf);
- switch(ccb->state) {
- case CALL:
- if (strncmp(ccb->buf,greeting_rsp,strlen(greeting_rsp)) == 0) {
- usprintf(ccb->socket,login_cmd,username,password);
- ccb->state = NMBR;
- } else {
- ccb->state = EXIT;
- }
- goto loop;
-
- case NMBR:
- switch (ccb->buf[0]) {
- case '#':
- ccb->folder_len = atoi(&(ccb->buf[1]));
- usprintf(ccb->socket,read_cur_cmd);
- ccb->state = SIZE;
- goto loop;
- case '+':
- /* If there is no mail (the only time we get a "+"
- * response back at this stage of the game),
- * then just close out the connection, because
- * there is nothing more to do!! */
- default:
- ccb->state = EXIT;
- }
- goto loop;
-
- case SIZE:
- if (ccb->buf[0] == '=') {
- ccb->msg_len = atol(&(ccb->buf[1]));
- if (ccb->msg_len > 0) {
- usprintf(ccb->socket,retr_cmd);
- ccb->state = XFER;
- if ((fd = open_file(Workfile_name,"a+",0,1)) == NULLFILE) {
- ccb->state = EXIT;
- goto loop;
- }
- fseek(fd,0,SEEK_SET);
- } else {
- ccb->state = EXIT;
- }
- } else
- ccb->state = EXIT;
- goto loop;
-
- case XFER:
- fprintf(fd,"%s\n",ccb->buf);
- /* Add CRLF */
- if((ccb->msg_len -= (long)(strlen(ccb->buf)+2)) > 0)
- goto loop;
- /* All done, so do local cleanup */
- if (mlock(Mailspool,mailbox_name)) {
- tprintf("Can't open mailbox, new mail in file %s\n",
- Workfile_name);
- ccb->state = EXIT;
- goto loop;
- }
- sprintf(mailbox_pathname,"%s/%s.txt",Mailspool,mailbox_name);
- mf = open_file(mailbox_pathname,"a+",0,1);
- if(mf == NULLFILE) {
- ccb->state = EXIT;
- goto loop;
- }
- fseek(fd,0,SEEK_SET);
-
- /* get first line */
- if (fgets(ccb->buf,BUF_LEN,fd) != NULLCHAR) {
- /* if pop server is not NOS then insert SOM */
- if (isNotSOM(&ccb->buf[0])) {
- char tmp[BUF_LEN];
- sprintf(tmp,"From POP2@%s at %s",
- inet_ntoa(mailhost),ptime(&currtime));
- fputs(tmp,mf);
- }
- /* copy all */
- fputs(ccb->buf,mf);
- while (!feof(fd)) {
- if(fgets(ccb->buf,BUF_LEN,fd) != NULLCHAR) {
- fputs(ccb->buf,mf);
- }
- }
- }
- fclose(mf);
- fclose(fd);
- fd = NULL;
- rmlock(Mailspool,mailbox_name);
- unlink(Workfile_name);
- usprintf(ccb->socket,ackd_cmd);
- if(Popquiet < 2)
- tprintf("New mail for %s from mailhost <%s> at %s%s",
- mailbox_name, inet_ntoa(mailhost),
- ctime(&currtime), (Popquiet < 1) ? "\007" : "");
-
- if(Popquiet == 3)
- log(ccb->socket,"POP2 new mail <%s>",inet_ntoa(mailhost));
-
- ccb->msg_num++;
- ccb->state = SIZE;
- goto loop;
-
- case EXIT:
- if (fd != NULLFILE)
- fclose(fd);
- default:
- goto loop;
- }
- }
- }
- if (fd != NULLFILE)
- fclose(fd);
- recvline(ccb->socket,ccb->buf,BUF_LEN);
- close_s(ccb->socket);
- xfree((char *)ccb);
- ccb = NULLCCB;
- start_timer(&popcli_t);
- return;
- }
-
- #endif /* POP2_CLIENT */
-